其他
Java丨Ele实验室“疫情传播仿真程序”的代码实现
https://blog.csdn.net/u013840066/article/details/104212919
视频中程序代码GitHub开源链接:
https://github.com/KikiLetGo/VirusBroadcast/tree/master/src
下面我们进入正题,运行效果图如下图所示:
该程序主要使用Swing( 一个为Java设计的GUI工具包)来绘制图形用户界面(GUI)。实现的步骤如下:
创建Point 类
该类用于定义绘制图形界面上的点,代码如下:
1public class Point {
2 private int x;
3 private int y;
4
5 public Point(int x, int y) {
6 this.x = x;
7 this.y = y;
8 }
9
10 public int getX() {
11 return x;
12 }
13
14 public void setX(int x) {
15 this.x = x;
16 }
17
18 public int getY() {
19 return y;
20 }
21
22 public void setY(int y) {
23 this.y = y;
24 }
25}
创建常量类
该类用于调整参数来展现不同的效果,见下方代码:
1public class Constants {
2 //初始感染数量
3 public static int ORIGINAL_COUNT=50;
4 //传播率
5 public static float BROAD_RATE = 0.8f;
6 //潜伏时间
7 public static float SHADOW_TIME = 140;
8 //医院收治响应时间
9 public static int HOSPITAL_RECEIVE_TIME=10;
10 //医院床位
11 public static int BED_COUNT=1000;
12 //流动意向平均值
13 public static float u=-0.99f;
14}
创建城市类
该类用于定义一个城市。
1public class City {
2 private int centerX;
3 private int centerY;
4
5 public City(int centerX, int centerY) {
6 this.centerX = centerX;
7 this.centerY = centerY;
8 }
9
10 public int getCenterX() {
11 return centerX;
12 }
13
14 public void setCenterX(int centerX) {
15 this.centerX = centerX;
16 }
17
18 public int getCenterY() {
19 return centerY;
20 }
21
22 public void setCenterY(int centerY) {
23 this.centerY = centerY;
24 }
25}
创建医院类
该类用于创建一个演示的医院类。
1public class Hospital {
2 private int x=800;
3 private int y=110;
4 private int width;
5 private int height=606;
6 public int getWidth() {
7 return width;
8 }
9 public int getHeight() {
10 return height;
11 }
12
13 public int getX() {
14 return x;
15 }
16
17 public int getY() {
18 return y;
19 }
20
21 private static Hospital hospital = new Hospital();
22 public static Hospital getInstance(){
23 return hospital;
24 }
25 private Point point = new Point(800,100);
26 private List<Bed> beds = new ArrayList<>();
27
28 private Hospital() {
29 if(Constants.BED_COUNT==0){
30 width=0;
31 height=0;
32 }
33 int column = Constants.BED_COUNT/100;
34 width = column*6;
35
36 for(int i=0;i<column;i++){
37
38 for(int j=10;j<=610;j+=6){
39 Bed bed = new Bed(point.getX()+i*6,point.getY()+j);
40 beds.add(bed);
41
42 }
43
44 }
45 }
46
47 public Bed pickBed(){
48 for(Bed bed:beds){
49 if(bed.isEmpty()){
50 return bed;
51 }
52 }
53 return null;
54 }
55}
创建医院的床位类
该类创建一个用于演示的医院的病床类。
1public class Bed extends Point{
2 public Bed(int x, int y) {
3 super(x, y);
4 }
5 private boolean isEmpty=true;
6
7 public boolean isEmpty() {
8 return isEmpty;
9 }
10
11 public void setEmpty(boolean empty) {
12 isEmpty = empty;
13 }
14}
创建PersonPool类
该类创建PersonPool,用于管理城市大小和人数。
1public class PersonPool {
2 private static PersonPool personPool = new PersonPool();
3 public static PersonPool getInstance(){
4 return personPool;
5 }
6
7 List<Person> personList = new ArrayList<Person>();
8
9 public List<Person> getPersonList() {
10 return personList;
11 }
12
13 private PersonPool() {
14 City city = new City(400,400);
15 for (int i = 0; i < 5000; i++) {
16 Random random = new Random();
17 int x = (int) (100 * random.nextGaussian() + city.getCenterX());
18 int y = (int) (100 * random.nextGaussian() + city.getCenterY());
19 if(x>700){
20 x=700;
21 }
22 Person person = new Person(city,x,y);
23 personList.add(person);
24 }
25 }
26}
创建Person类
1public class Person {
2 private City city;
3 private int x;
4 private int y;
5 private MoveTarget moveTarget;
6 int sig=1;
7
8
9 double targetXU;
10 double targetYU;
11 double targetSig=50;
12
13
14 public interface State{
15 int NORMAL = 0;
16 int SUSPECTED = NORMAL+1;
17 int SHADOW = SUSPECTED+1;
18
19 int CONFIRMED = SHADOW+1;
20 int FREEZE = CONFIRMED+1;
21 int CURED = FREEZE+1;
22 }
23
24 public Person(City city, int x, int y) {
25 this.city = city;
26 this.x = x;
27 this.y = y;
28 targetXU = 100*new Random().nextGaussian()+x;
29 targetYU = 100*new Random().nextGaussian()+y;
30
31 }
32 public boolean wantMove(){
33 double value = sig*new Random().nextGaussian()+Constants.u;
34 return value>0;
35 }
36
37 private int state=State.NORMAL;
38
39 public int getState() {
40 return state;
41 }
42
43 public void setState(int state) {
44 this.state = state;
45 }
46
47 public int getX() {
48 return x;
49 }
50
51 public void setX(int x) {
52 this.x = x;
53 }
54
55 public int getY() {
56 return y;
57 }
58
59 public void setY(int y) {
60 this.y = y;
61 }
62 int infectedTime=0;
63 int confirmedTime=0;
64 public boolean isInfected(){
65 return state>=State.SHADOW;
66 }
67 public void beInfected(){
68 state = State.SHADOW;
69 infectedTime=MyPanel.worldTime;
70 }
71
72 public double distance(Person person){
73 return Math.sqrt(Math.pow(x-person.getX(),2)+Math.pow(y-person.getY(),2));
74 }
75
76 private void freezy(){
77 state = State.FREEZE;
78 }
79 private void moveTo(int x,int y){
80 this.x+=x;
81 this.y+=y;
82 }
83 private void action(){
84 if(state==State.FREEZE){
85 return;
86 }
87 if(!wantMove()){
88 return;
89 }
90 if(moveTarget==null||moveTarget.isArrived()){
91
92 double targetX = targetSig*new Random().nextGaussian()+targetXU;
93 double targetY = targetSig*new Random().nextGaussian()+targetYU;
94 moveTarget = new MoveTarget((int)targetX,(int)targetY);
95
96 }
97
98
99 int dX = moveTarget.getX()-x;
100 int dY = moveTarget.getY()-y;
101 double length=Math.sqrt(Math.pow(dX,2)+Math.pow(dY,2));
102
103 if(length<1){
104 moveTarget.setArrived(true);
105 return;
106 }
107 int udX = (int) (dX/length);
108 if(udX==0&&dX!=0){
109 if(dX>0){
110 udX=1;
111 }else{
112 udX=-1;
113 }
114 }
115 int udY = (int) (dY/length);
116 if(udY==0&&udY!=0){
117 if(dY>0){
118 udY=1;
119 }else{
120 udY=-1;
121 }
122 }
123
124 if(x>700){
125 moveTarget=null;
126 if(udX>0){
127 udX=-udX;
128 }
129 }
130 moveTo(udX,udY);
131
132// if(wantMove()){
133// }
134
135
136 }
137
138 private float SAFE_DIST = 2f;
139
140 public void update(){
141 //@TODO找时间改为状态机
142 if(state>=State.FREEZE){
143 return;
144 }
145 if(state==State.CONFIRMED&&MyPanel.worldTime-confirmedTime>=Constants.HOSPITAL_RECEIVE_TIME){
146 Bed bed = Hospital.getInstance().pickBed();
147 if(bed==null){
148 System.out.println("隔离区没有空床位");
149 }else{
150 state=State.FREEZE;
151 x=bed.getX();
152 y=bed.getY();
153 bed.setEmpty(false);
154 }
155 }
156 if(MyPanel.worldTime-infectedTime>Constants.SHADOW_TIME&&state==State.SHADOW){
157 state=State.CONFIRMED;
158 confirmedTime = MyPanel.worldTime;
159 }
160
161 action();
162
163 List<Person> people = PersonPool.getInstance().personList;
164 if(state>=State.SHADOW){
165 return;
166 }
167 for(Person person:people){
168 if(person.getState()== State.NORMAL){
169 continue;
170 }
171 float random = new Random().nextFloat();
172 if(random<Constants.BROAD_RATE&&distance(person)<SAFE_DIST){
173 this.beInfected();
174 }
175 }
176 }
177}
创建MyPanel类
1public class MyPanel extends JPanel implements Runnable {
2
3
4 private int pIndex=0;
5
6 public MyPanel() {
7 this.setBackground(new Color(0x444444));
8 }
9
10 @Override
11 public void paint(Graphics arg0) {
12 super.paint(arg0);
13 //draw border
14 arg0.setColor(new Color(0x00ff00));
15 arg0.drawRect(Hospital.getInstance().getX(),Hospital.getInstance().getY(),
16 Hospital.getInstance().getWidth(),Hospital.getInstance().getHeight());
17
18
19
20 List<Person> people = PersonPool.getInstance().getPersonList();
21 if(people==null){
22 return;
23 }
24 people.get(pIndex).update();
25 for(Person person:people){
26
27 switch (person.getState()){
28 case Person.State.NORMAL:{
29 arg0.setColor(new Color(0xdddddd));
30
31 }break;
32 case Person.State.SHADOW:{
33 arg0.setColor(new Color(0xffee00));
34
35 }break;
36 case Person.State.CONFIRMED:
37 case Person.State.FREEZE:{
38 arg0.setColor(new Color(0xff0000));
39
40 }break;
41 }
42 person.update();
43 arg0.fillOval(person.getX(), person.getY(), 3, 3);
44
45 }
46 pIndex++;
47 if(pIndex>=people.size()){
48 pIndex=0;
49 }
50 }
51
52 public static int worldTime=0;
53 @Override
54 public void run() {
55 while (true) {
56
57 this.repaint();
58
59 try {
60 Thread.sleep(100);
61 worldTime++;
62 } catch (InterruptedException e) {
63 e.printStackTrace();
64 }
65 }
66
67 }
68
69
70}
创建MoveTarget 类
创建MoveTarget 类用于模拟人群流动。
1public class MoveTarget {
2 private int x;
3 private int y;
4 private boolean arrived=false;
5
6 public MoveTarget(int x, int y) {
7 this.x = x;
8 this.y = y;
9 }
10
11 public int getX() {
12 return x;
13 }
14
15 public void setX(int x) {
16 this.x = x;
17 }
18
19 public int getY() {
20 return y;
21 }
22
23 public void setY(int y) {
24 this.y = y;
25 }
26
27 public boolean isArrived() {
28 return arrived;
29 }
30
31 public void setArrived(boolean arrived) {
32 this.arrived = arrived;
33 }
34}
修改入口类
修改入口类,绘制图形
1import javax.swing.*;
2import java.awt.image.BufferedImage;
3import java.util.ArrayList;
4import java.util.List;
5import java.util.Random;
6
7public class Main {
8 public static void main(String[] args) {
9 MyPanel p = new MyPanel();
10 Thread panelThread = new Thread(p);
11 JFrame frame = new JFrame();
12 frame.add(p);
13 frame.setSize(1000, 800);
14 frame.setLocationRelativeTo(null);
15 frame.setVisible(true);
16 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
17 panelThread.start();
18
19 List<Person> people = PersonPool.getInstance().getPersonList();
20 for(int i=0;i<Constants.ORIGINAL_COUNT;i++){
21 int index = new Random().nextInt(people.size()-1);
22 Person person = people.get(index);
23
24 while (person.isInfected()){
25 index = new Random().nextInt(people.size()-1);
26 person = people.get(index);
27 }
28 person.beInfected();
29 }
30 }
31}
到此完成,运行程序即可。
图书推荐
《Spring Boot实战派》
龙中华 著
让开发像搭积木一样简单,在实战情景中学习,学完即知怎么实战
版本点新 针对 Spring Boot 2.0 及以上版本
体例科学 用“知识点+实例”形式编写 实例丰富 58个基础实例 + 2个综合项目 对比选优 对比讲解多种同类技术,便于技术选型,如 Spring Security 和 Shiro、Elasticsearch 和 Solr、JPA 和 Mybatis 技术点新 讲解了时下流行的接口架构风格 RESTful 、用来实现高并发的 Redis 、以及用来实现系统间通信的中间件 RabbitMQ▊ 关于作者
龙中华
12年来一直在某一线互联网公司担任资深系统分析师。
目前带领3个研发团队,承担系统的分析、设计、实施、演进,以及技术团队管理和培训等职责。有独到的团队建设和管理经验,对互联网多种技术特点和发展趋势有较深入的研究,对多种技术(如 Spring Boot 、Spring Cloud 和 Service Mesh )有深入的研究和实战经验。
(扫码了解本书详情)
热文推荐
▼ 点击阅读原文,访问作者博客。